package com.gmlive.common.imageloader.fresco

import android.graphics.Bitmap
import android.widget.ImageView
import com.facebook.common.executors.UiThreadImmediateExecutorService
import com.facebook.common.references.CloseableReference
import com.facebook.datasource.DataSource
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.generic.GenericDraweeHierarchy
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder
import com.facebook.drawee.interfaces.DraweeController
import com.facebook.drawee.view.SimpleDraweeView
import com.facebook.imagepipeline.common.ResizeOptions
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
import com.facebook.imagepipeline.image.CloseableImage
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
import com.gmlive.common.imageloader.ImageLoader
import com.gmlive.common.imageloader.isAvailable
import com.gmlive.common.imageloader.request.Request

/**
 *  Create by: fanfeiyue
 *  on: 2019-11-27
 *  desc:
 */
object IkFresco {
    private const val TAG = "IkFresco"

    fun intoImage(view: SimpleDraweeView, request: Request) {
        val imgRequest = createImgRequest(request)
        val draweeController = createDraweeController(request, imgRequest, view)
        val hierarchy = createHierarchy(view, request)
        request.centerCrop?.let { view.scaleType = ImageView.ScaleType.CENTER_CROP }
        view.hierarchy = hierarchy
        view.controller = draweeController
    }

    fun intoImage(view: ImageView, request: Request) {
        request.placeHolderDrawable?.let {
            view.setImageDrawable(it)
        }
        val imgRequest = createImgRequest(request)
        val dataSource = Fresco.getImagePipeline().fetchDecodedImage(imgRequest, TAG)
        dataSource.subscribe(object : BaseBitmapDataSubscriber() {
            override fun onNewResultImpl(bitmap: Bitmap?) {
                if (bitmap.isAvailable()) {
                    view.setImageBitmap(bitmap)
                } else {
                    request.errorDrawable?.let { view.setImageDrawable(it) }
                }
            }

            override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
                request.errorDrawable?.let {
                    view.setImageDrawable(it)
                }
            }
        }, UiThreadImmediateExecutorService.getInstance())
    }

    fun getBitmap(picId: Int, request: Request, bitmapLoadListener: ((picId: Int, bitmap: Bitmap?) -> Unit)?) {
        val imgRequest = createImgRequest(request)
        val imgPipeline = Fresco.getImagePipeline()
        imgPipeline.fetchDecodedImage(imgRequest, TAG)
                .subscribe(object : BaseBitmapDataSubscriber() {
                    override fun onNewResultImpl(bitmap: Bitmap?) {
                        var resultBitmap: Bitmap? = null

                        try {
                            resultBitmap = bitmap.takeIf { it.isAvailable() }?.let { it.copy(it.config, it.isMutable) }
                        } catch (e: Exception) {
                            e.printStackTrace()
                        }
                        bitmapLoadListener?.invoke(picId, resultBitmap)
                    }

                    override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
                        bitmapLoadListener?.invoke(picId, null)

                    }
                }, UiThreadImmediateExecutorService.getInstance())
    }

    private fun createImgRequest(request: Request): ImageRequest {
        return ImageRequestBuilder.newBuilderWithSource(request.uri).let { imgRequestBuilder ->
            request.sizeOption?.let { imgRequestBuilder.setResizeOptions(ResizeOptions(it.width, it.height)) }
            imgRequestBuilder.build()
        }
    }

    private fun createHierarchy(view: SimpleDraweeView, request: Request): GenericDraweeHierarchy {
        var hierarchy = view.hierarchy
        if (hierarchy == null) hierarchy = GenericDraweeHierarchyBuilder(ImageLoader.app.resources).build()
        hierarchy.fadeDuration = 150
        request.placeHolderDrawable?.let { hierarchy.setPlaceholderImage(it) }
        request.errorDrawable?.let { hierarchy.setFailureImage(it) }
        return hierarchy
    }

    private fun createDraweeController(request: Request, imageRequest: ImageRequest, view: SimpleDraweeView): DraweeController {
        return Fresco.newDraweeControllerBuilder().let { controllerBuilder ->
            controllerBuilder.imageRequest = imageRequest
            controllerBuilder.oldController = view.controller
            request.autoPlay?.let { controllerBuilder.setAutoPlayAnimations(it) }
            controllerBuilder.build()
        }
    }
}